import {
  Graph, Addon, Vector, Shape,
} from '@antv/x6';
import './shape'; // 注册相关节点
import { cloneDeep } from 'lodash';
import { initformData, commonEdage } from '../const/config';
// import { initformData } from '../const/config';
import { SimpleNodeView } from './view';

export default class DagGraph {
  static init(id, minimapId) {
    const container = document.querySelector(id);
    const minimapContainer = document.querySelector(minimapId);
    this.graph = new Graph({
      container,
      autoResize: container,
      background: {
        color: '#f5f5f5', // 设置画布背景颜色
      },
      minimap: {
        enabled: true,
        container: minimapContainer || container,
        width: 250,
        height: 160,
        padding: 10,
        graphOptions: {
          async: true,
          // eslint-disable-next-line consistent-return
          getCellView(cell) {
            // 用指定的 View 替换节点默认的 View
            if (cell.isNode()) {
              return SimpleNodeView;
            }
            // return cell;
          },
          // eslint-disable-next-line consistent-return
          createCellView(cell) {
            // 在小地图中不渲染边
            if (cell.isEdge()) {
              return null;
            }
            // return cell;
          },
        },
      },
      // width: 500,
      // height: 500,
      // grid: {
      //   size: 10,
      //   visible: true,
      //   type: 'dot', // 'dot' | 'fixedDot' | 'mesh'
      //   args: {
      //     color: '#a05410', // 网格线/点颜色
      //     thickness: 1, // 网格线宽度/网格点大小
      //   },
      // },
      // 画布调整
      scroller: {
        enabled: true,
        pageVisible: true,
        pageBreak: true,
        pannable: true,
        // modifiers: "ctrl",
        autoResize: true,
      },
      // 设置滚轮缩放画布
      mousewheel: true,
      snapline: false, // 对齐线
      history: true, // 历史
      clipboard: true, // 复制
      keyboard: true,
      // 按ctrl框选节点
      selecting: {
        multiple: true,
        enabled: true,
        rubberband: true,
        modifiers: 'ctrl',
        strict: true,
        movable: true,
        showNodeSelectionBox: false,
        showEdgeSelectionBox: false,
      },
      // 配置全局连线规则
      connecting: {
        anchor: 'midSide',
        connector: 'algo-connector',
        connectionPoint: 'anchor',
        allowBlank: false,
        allowLoop: false,
        allowNode: false,
        allowMulti: false,
        allowEdge: false,
        highlight: true,
        snap: {
          radius: 25,
        },
        createEdge() {
          const newEdge = new Shape.Edge(cloneDeep(commonEdage));
          return newEdge;
          // return this.graph.createEdge({
          //   shape: 'dag-edge',
          //   attrs: {
          //     line: {
          //       strokeDasharray: '5 5',
          //       targetMarker: {
          //         name: 'block',
          //         width: 12,
          //         height: 8,
          //       },
          //     },
          //   },
          //   zIndex: -1,
          // });
        },
        // 在移动边的时候判断连接是否有效，如果返回 false，当鼠标放开的时候，不会连接到当前元素，否则会连接到当前元素
        // https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#validateconnection
        // validateConnection({
        //   sourceView,
        //   targetView,
        //   sourceMagnet,
        //   targetMagnet,
        // }) {
        //   if (sourceView === targetView) {
        //     return false;
        //   }
        //   if (!sourceMagnet) {
        //     return false;
        //   }
        //   // 只能连接到输入链接桩
        //   if (
        //     !targetMagnet
        //     || targetMagnet.getAttribute('port-group') !== 'in'
        //   ) {
        //     return false;
        //   }
        //   return true;
        // },
        highlighting: {
          magnetAvailable: {
            name: 'stroke',
            args: {
              padding: 4,
              attrs: {
                strokeWidth: 4,
                stroke: '#31a3ff', // rgba(223,234,255)  #e52e1a
              },
            },
          },
        },
      },
      // 节点拖拽到另一节点，形成父子节点关系
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox();
          return this.getNodes().filter((n) => {
            // 只有 data.parent 为 true 的节点才是父节点
            const data = n.getData();
            if (data && data.parent) {
              const targetBBox = n.getBBox();
              return bbox.isIntersectWithRect(targetBBox);
            }
            return false;
          });
        },
      },
    });
    // this.initStencil(stencilId);
    // this.initShape();
    this.initEvent();
    // this.initAnimate();
    return this.graph;
  }

  //  初始化自定义模型树列表
  static initStencilTree(id) {
    const stencilWrap = document.querySelector(id);
    this.dnd = new Addon.Dnd({
      target: this.graph,
      scaled: true,
      containerParent: stencilWrap,
    });

    // stencilWrap.appendChild(this.dnd.container);
  }

  // 初始化加载 拖拽组件列表
  static initStencil(id) {
    const { graph } = this;
    this.stencil = new Addon.Stencil({
      title: '组件列表',
      target: this.graph,
      placeholder: '搜索',
      search(cell, keyword) {
        const text = cell.attr('label/text') || '';
        return text.includes(keyword);
      },
      getDragNode(node) {
        // let shape = node.shape;
        // let metaData = cloneDeep(commonMetadata[shape]);
        // newNode.setProp(metaData);
        // console.log('getDragNode', node);
        const shape = node.attr('body/mapShape');
        // console.log('getDragNode shape data', initformData[shape]);
        // 自定义组件
        const data = {
          nodename: node.attr('label/text'),
          inParams: '',
          outParams: '',
          label: node.attr('label/text'),
          status: 'default',
        };

        const newNode = graph.createNode({
          shape,
          data: initformData[shape] ? cloneDeep(initformData[shape]) : data,
        });
        console.log('getDragNode newNode', newNode);

        return newNode;
      },
      notFoundText: '没有找到匹配的节点',
      stencilGraphWidth: 240,
      collapsable: true,
      scaled: true,
      groups: [
        {
          name: 'group_a',
          title: '基础操作',
          graphHeight: 200,
          layoutOptions: {
            columns: 1,
            marginX: 30,
            marginY: 10,
            rowHeight: 50,
          },
        },
        {
          name: 'group_b',
          title: '业务组件',
          graphHeight: 800,
          layoutOptions: {
            columns: 1,
            marginX: 30,
            marginY: 10,
            rowHeight: 48,
          },
        },
      ],
    });
    const stencilWrap = document.querySelector(id);
    stencilWrap.appendChild(this.stencil.container);
    this.initShape();
  }

  static initShape() {
    const { graph } = this;
    // shape.js中注册的组件
    const a1 = graph.createNode({
      shape: 'pipeline',
      attrs: {
        body: {
          mapShape: 'pipeline',
        },
        label: {
          text: '算法组件',
        },
      },
      // data: cloneDeep(pipeline)
    });
    const a2 = graph.createNode({
      shape: 'fork',
      attrs: {
        body: {
          mapShape: 'fork',
        },
        label: {
          text: '判断节点',
        },
      },
      // data: cloneDeep(decision)
    });
    // 自定义组件
    const d1 = graph.createNode({
      shape: 'dag-condition',
      attrs: {
        body: {
          mapShape: 'dag-condition',
        },
        label: {
          text: '条件组件',
        },
      },
    });
    const d2 = graph.createNode({
      shape: 'dag-onlyIn',
      attrs: {
        body: {
          mapShape: 'dag-onlyIn',
        },
        label: {
          text: '输入组件',
        },
      },
    });
    const d3 = graph.createNode({
      shape: 'dag-node',
      attrs: {
        body: {
          mapShape: 'dag-node',
        },
        label: {
          text: '数据组件',
        },
      },
    });
    const d4 = graph.createNode({
      shape: 'dag-output',
      attrs: {
        body: {
          mapShape: 'dag-output',
        },
        label: {
          text: '输出组件',
        },
      },
    });

    this.stencil.load([a1, a2], 'group_a');
    this.stencil.load([d1, d2, d3, d4], 'group_b');
  }

  static initGraphShape(data) {
    this.graph.fromJSON(data);
  }

  static showPorts(ports, show) {
    for (let i = 0, len = ports.length; i < len; i += 1) {
      // eslint-disable-next-line no-param-reassign
      ports[i].style.visibility = show ? 'visible' : 'hidden';
    }
  }

  static initEvent() {
    const { graph } = this;
    // 选中节点/边  #31a3ff
    graph.on('cell:selected', ({ cell }) => {
      if (cell.isEdge()) {
        cell.attr('line/stroke', '#07f5f5');
        cell.attr('line/strokeWidth', 2.5);
      } else {
        // cell.attr("body/stroke", "#07f5f5");
        // cell.attr("body/strokeWidth", 2.5);
        cell.setAttrs({
          body: {
            fill: '#2cfeff',
            stroke: '#2cfeff',
            fillOpacity: '1',
            strokeOpacity: '1',
          },
          label: {
            fill: '#151B21',
          },
          path: {
            fill: '#151B21',
          },
          path2: {
            fill: '#151B21',
          },
        });
      }
    });
    // 取消选中节点/边时触发
    graph.on('cell:unselected', ({ cell }) => {
      if (cell.isEdge()) {
        cell.attr('line/stroke', '#2cfeff');
        cell.attr('line/strokeWidth', 1);
      } else {
        // console.log('unselected');
        cell.setAttrs({
          body: {
            fill: '#2cfeff',
            stroke: '#2cfeff',
            fillOpacity: '0.15',
            strokeOpacity: '0.6',
          },
          label: {
            fill: '#2CFEFF',
          },
          path: {
            fill: '#2CFEFF',
          },
          path2: {
            fill: '#2CFEFF',
          },
        });
        // cell.attr("body/stroke", "#2cfeff");
        // cell.attr("body/strokeWidth", 1);
      }
    });
    // 给相应的边添加标签；
    graph.on('edge:connected', ({ isNew, edge }) => {
      if (isNew) {
        const source = edge.getSourceCell();
        const rightPorts = source.getPortsByGroup('out');
        if (rightPorts.length === 2) {
          const sourcePortId = edge.getSourcePortId();
          const portIndex = source.getPortIndex(sourcePortId);
          const label = portIndex === 1 ? '是' : '否';
          edge.setLabels(label);
        }
      }
    });
  }

  static initAnimate() {
    const { graph } = this;
    const flash = (cell) => {
      const cellView = graph.findViewByCell(cell);
      if (cellView) {
        cellView.highlight();
        setTimeout(() => cellView.unhighlight(), 350);
      }
    };
    graph.on('signal', (cell) => {
      if (cell.isEdge()) {
        const view = graph.findViewByCell(cell);
        if (view) {
          const token = Vector.create('circle', { r: 6, fill: '#feb662' });
          const target = cell.getTargetCell();
          setTimeout(() => {
            view.sendToken(token.node, 1200, () => {
              if (target) {
                graph.trigger('signal', target);
              }
            });
          }, 350);
        }
      } else {
        flash(cell);
        const edges = graph.model.getConnectedEdges(cell, {
          outgoing: true,
        });
        edges.forEach((edge) => graph.trigger('signal', edge));
      }
    });
    graph.on('node:mousedown', ({ cell }) => {
      graph.trigger('signal', cell);
    });
  }

  // 销毁
  static destroy() {
    this.graph.dispose();
  }
}
